using System;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;

namespace CloudClipboardSync.MvvmFw
{
    public static class ExtensionMethods
    {
        public static void Raise(this PropertyChangedEventHandler notify, string propertyName, object sender)
        {
            if(notify != null)
                notify(sender, new PropertyChangedEventArgs(propertyName));
        }

        public static void Raise(this PropertyChangedEventHandler handler, Expression<Func<object>> expression, object sender)
        {
            handler.Raise(ExpressionUtils.PropertyToString(expression), sender);
        }

        public static void NotifyPropertyChanged<T>(this T obj, params Expression<Func<T, object>>[] expressions) where T : IPublicNotifyPropertyChanged
        {
            foreach(var expr in expressions)
                obj.NotifyPropertyChanged(ExpressionUtils.PropertyToString(expr));
        }

        public static void NotifyPropertyChanged<T>(this T obj, params Expression<Func<object>>[] expressions) where T : IPublicNotifyPropertyChanged
        {
            foreach (var expr in expressions)
                obj.NotifyPropertyChanged(ExpressionUtils.PropertyToString(expr));
        }

        public static void OnPropertyChanged<T>(this T obj, Expression<Func<T, object>> expression, Action<T> action) 
            where T: INotifyPropertyChanged
        {
            var propName = ExpressionUtils.PropertyToString(expression);
            obj.PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == propName)
                    action(obj);
            };
        }

        public static void OnPropertyChanged<T>(this T obj, Expression<Func<T, object>> expression, Action action)
            where T : INotifyPropertyChanged
        {
            var propName = ExpressionUtils.PropertyToString(expression);
            obj.PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == propName)
                    action();
            };
        }

        public static void OnMultiplePropertyChanged<T>(this T obj, Action action, params Expression<Func<T, object>>[] expressions)
            where T : INotifyPropertyChanged
        {
            var propNames = expressions.Select(ExpressionUtils.PropertyToString).ToArray();

            obj.PropertyChanged += (sender, args) =>
            {
                if (propNames.Contains(args.PropertyName))
                    action();
            };
        }
    }
}